﻿using System;
using System.Threading;
using Porownywarka.Interfejsy;

namespace Porownywarka.Sortowanie
{
    public class MergeSort<T> :  ISortMethod<T>
        where T : IComparable<T>
    {
        public T[] SortedData { get; private set; }

        public T[] Sort(T[] tablica, object l)
        {
            T[] tab3;
            T[] tab2;

            lock (l)
            {
                tab3 = (T[])tablica.Clone();
                tab2 = (T[])tablica.Clone();
            }

            //T[] tab2 = (T[])tablica.Clone();
            //T[] tab3 = (T[])tablica.Clone();
            SortedData = tab3;
            return Sort(tab3, 0, tab3.Length - 1, tab2, 0, 1);

        }

        private T[] Sort(T[] cel, int pocz, int kon, T[] źródło,
            int głębokość, int próg)
        {
            if (kon - pocz < 1)
                throw new Exception("Brak elementów do posortowania!");

            int s = (pocz + kon) / 2;
            if (głębokość >= próg)
            {
                Sort(źródło, pocz, s, cel, głębokość + 1, próg);
                Sort(źródło, s + 1, kon, cel, głębokość + 1, próg);
            }
            else
            {
                Thread w1 = new Thread(
                    delegate()
                    {
                        Sort(źródło, pocz, s, cel, głębokość + 1, próg);
                    }
                );
                w1.Start();
                Thread w2 = new Thread(
                    delegate()
                    {
                        Sort(źródło, s + 1, kon, cel, głębokość + 1, próg);
                    }
                );
                w2.Start();
                w1.Join();
                w2.Join();
            }
            Połącz(źródło, pocz, s, kon, cel);

            return cel;
        }

        private void Połącz(T[] źródło, int pocz, int s, int kon, T[] cel)
        {
            int i1 = pocz, i2 = s + 1, i3 = pocz;
            while (i1 <= s || i2 <= kon)
                if (i1 <= s && (i2 > kon || źródło[i1].CompareTo(źródło[i2]) <= 0))
                    cel[i3++] = źródło[i1++];
                else
                    cel[i3++] = źródło[i2++];
        }

    }
}
